package uk.ac.ebi.curtain.exec;

import java.io.File;
import java.io.IOException;
import java.util.List;

import uk.ac.ebi.curtain.utils.CurtainUncheckedException;
import uk.ac.ebi.curtain.utils.data.FileType;
import uk.ac.ebi.curtain.utils.data.ReadType;
import uk.ac.ebi.curtain.utils.file.SequenceQualityType;
import uk.ac.ebi.curtain.utils.io.impl.FileIO;
import uk.co.flamingpenguin.jewel.cli.ArgumentValidationException;
import uk.co.flamingpenguin.jewel.cli.CliFactory;
import uk.co.flamingpenguin.jewel.cli.Option;

public class FilterFastqByQualityScore {

	private static interface FilterFastqByQualityScope {
		
		@Option(shortName = "o", description="Output file(s). If two files provided (and input files are paired) " +
				"the output will be split between them.")
		public List<File> getOutput();
		
		public boolean isOutput();
		// defaultValue=new String[]{SequenceQualityType.Sanger.toString()}
		@Option(shortName = "e", defaultValue="Sanger",description="Quality score encoding: Sanger, Illumina (1.3+)")
		public SequenceQualityType getMethod();
		
		public boolean isMethod();
		
		@Option(shortName="i",description="Input file(s) - if two files are provided, the Paired flag has to be set!!!")
		public List<File> getFiles();
		
		public boolean isFiles();
		
		@Option(shortName="p",description="Paired file flag - if one file is proveded and this flag is set, the input file is understand to be shuffeled")
		public boolean getPaired();
		
		public boolean isPaired();
		
		@Option(shortName="l",description="Minimum read length, before excluded", defaultValue="30")
		public Integer getMinLength();
		
		@Option(shortName="q", description="Minimum average quality to keep over tile", defaultValue="30")
		public Integer getMinQuality();	
		
		@Option(shortName="t", description="Tile length to evaluate", defaultValue="20")
		public Integer getTileLength();
		
//		@Option(helpRequest = true, description = "display helpfull menu", shortName = "h")
//		boolean getHelp();		
	}
	
	public static void main(String[] args) {
		FilterFastqByQualityScope param = null;
		try {
			param = CliFactory.parseArguments(FilterFastqByQualityScope.class, args);
		} catch (ArgumentValidationException e1) {
			throw new CurtainUncheckedException("Problems parsing arguments",e1);
		}
		if(param.getOutput().size() > 2){
			throw new IllegalArgumentException("Maximum of 2 files allowed as output (in case of paired)");
		}
		if(param.getFiles().size() > 2){
			throw new IllegalArgumentException("Maximum of 2 files allowed as input (in case of paired)");
		}
		if(param.getOutput().size() > 1 && !param.isPaired()){
			throw new IllegalArgumentException("Two input files provided - paired flag has to be set to enable splitting!");
		}
		if(param.getFiles().size() > 1 && !param.isPaired()){
			throw new IllegalArgumentException("Two input files provided - paired flag has to be set to process paired files!");
		}
		if(param.getOutput().isEmpty()){
			throw new IllegalArgumentException("Not output file(s) provided!!!");
		}
		if(param.getFiles().isEmpty()){
			throw new IllegalArgumentException("Not input file(s) provided!!!");
		}
		

		final ReadType rtype = param.isPaired()?ReadType.ShortPaired: ReadType.Short;
		
		File[] outFileArr = param.getOutput().toArray(new File[0]);

		BulkFilterFastqByQualityScore filter = new BulkFilterFastqByQualityScore(outFileArr.length);
		filter.setMinQual(param.getMinQuality());
		filter.setMinLength(param.getMinLength());
		filter.setTileLen(param.getTileLength());
		filter.setFileType(FileType.fastq);


		filter.setInputType(SequenceQualityType.Sanger);
		if(param.isMethod()){
			filter.setInputType(param.getMethod());
		}
		filter.setTargetType(filter.getInputType());
		
		try {
			for(int i = 0; i < outFileArr.length; ++i){
				filter.setOutput(i, new FileIO(outFileArr[i]).getPrintWriter());
			}
			File[] inArray = param.getFiles().toArray(new File[0]);
			filter.process(inArray);
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			for(int i = 0; i < outFileArr.length; ++i){
				FileIO.closeQuietly(filter.setOutput(i, null));
			}
			FileIO.closeQuietly(filter.setErrOut(null));
		}		
	}	
}
